import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Review } from './entities/review.entity';
import { CreateReviewDto } from './dto/create-review.dto';
import { UpdateReviewDto } from './dto/update-review.dto';
import { QueryReviewsDto } from './dto/query-reviews.dto';

@Injectable()
export class ReviewsService {
  constructor(
    @InjectRepository(Review)
    private reviewsRepository: Repository<Review>,
  ) {}

  async create(userId: number, createReviewDto: CreateReviewDto): Promise<Review> {
    // 检查用户是否已经评论过该工具
    const existingReview = await this.reviewsRepository.findOne({
      where: {
        toolId: createReviewDto.toolId,
        userId: userId,
      },
    });

    if (existingReview) {
      throw new ForbiddenException('您已经评论过该工具了');
    }

    const review = this.reviewsRepository.create({
      ...createReviewDto,
      userId,
      status: 'approved', // 可以改为 'pending' 需要审核
    });

    return await this.reviewsRepository.save(review);
  }

  async findAll(queryDto: QueryReviewsDto) {
    const {
      toolId,
      userId,
      status = 'approved',
      sortBy = 'latest',
      page = 1,
      limit = 10,
      minRating,
      maxRating,
    } = queryDto;

    const query = this.reviewsRepository
      .createQueryBuilder('review')
      .leftJoinAndSelect('review.user', 'user')
      .leftJoinAndSelect('review.tool', 'tool');

    // 筛选条件
    if (toolId) {
      query.andWhere('review.toolId = :toolId', { toolId });
    }

    if (userId) {
      query.andWhere('review.userId = :userId', { userId });
    }

    if (status) {
      query.andWhere('review.status = :status', { status });
    }

    if (minRating) {
      query.andWhere('review.rating >= :minRating', { minRating });
    }

    if (maxRating) {
      query.andWhere('review.rating <= :maxRating', { maxRating });
    }

    // 排序
    switch (sortBy) {
      case 'latest':
        query.orderBy('review.createdAt', 'DESC');
        break;
      case 'oldest':
        query.orderBy('review.createdAt', 'ASC');
        break;
      case 'highest':
        query.orderBy('review.rating', 'DESC');
        break;
      case 'lowest':
        query.orderBy('review.rating', 'ASC');
        break;
      case 'helpful':
        query.orderBy('review.helpfulCount', 'DESC');
        break;
      default:
        query.orderBy('review.createdAt', 'DESC');
    }

    // 分页
    const skip = (page - 1) * limit;
    query.skip(skip).take(limit);

    const [reviews, total] = await query.getManyAndCount();

    return {
      data: reviews,
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  async findOne(id: number): Promise<Review> {
    const review = await this.reviewsRepository.findOne({
      where: { id },
      relations: ['user', 'tool'],
    });

    if (!review) {
      throw new NotFoundException('评论不存在');
    }

    return review;
  }

  async update(id: number, userId: number, updateReviewDto: UpdateReviewDto): Promise<Review> {
    const review = await this.findOne(id);

    if (review.userId !== userId) {
      throw new ForbiddenException('您没有权限修改此评论');
    }

    Object.assign(review, updateReviewDto);
    return await this.reviewsRepository.save(review);
  }

  async remove(id: number, userId: number): Promise<void> {
    const review = await this.findOne(id);

    if (review.userId !== userId) {
      throw new ForbiddenException('您没有权限删除此评论');
    }

    await this.reviewsRepository.remove(review);
  }

  async markHelpful(id: number, helpful: boolean): Promise<Review> {
    const review = await this.findOne(id);

    if (helpful) {
      review.helpfulCount += 1;
    } else {
      review.notHelpfulCount += 1;
    }

    return await this.reviewsRepository.save(review);
  }

  // 获取工具的评分统计
  async getToolRatingStats(toolId: number) {
    const reviews = await this.reviewsRepository.find({
      where: { toolId, status: 'approved' },
    });

    if (reviews.length === 0) {
      return {
        averageRating: 0,
        totalReviews: 0,
        ratingDistribution: {
          5: 0,
          4: 0,
          3: 0,
          2: 0,
          1: 0,
        },
        dimensionRatings: {
          performance: 0,
          price: 0,
          easeOfUse: 0,
          documentation: 0,
        },
      };
    }

    const totalReviews = reviews.length;
    const sumRating = reviews.reduce((sum, review) => sum + Number(review.rating), 0);
    const averageRating = sumRating / totalReviews;

    // 评分分布
    const ratingDistribution = {
      5: reviews.filter((r) => Number(r.rating) === 5).length,
      4: reviews.filter((r) => Number(r.rating) === 4).length,
      3: reviews.filter((r) => Number(r.rating) === 3).length,
      2: reviews.filter((r) => Number(r.rating) === 2).length,
      1: reviews.filter((r) => Number(r.rating) === 1).length,
    };

    // 多维度评分平均值
    const dimensionRatings = {
      performance: this.calculateAverage(reviews, 'performanceRating'),
      price: this.calculateAverage(reviews, 'priceRating'),
      easeOfUse: this.calculateAverage(reviews, 'easeOfUseRating'),
      documentation: this.calculateAverage(reviews, 'documentationRating'),
    };

    return {
      averageRating: Number(averageRating.toFixed(1)),
      totalReviews,
      ratingDistribution,
      dimensionRatings,
    };
  }

  private calculateAverage(reviews: Review[], field: string): number {
    const validReviews = reviews.filter((r) => r[field] !== null);
    if (validReviews.length === 0) return 0;

    const sum = validReviews.reduce((sum, review) => sum + Number(review[field]), 0);
    return Number((sum / validReviews.length).toFixed(1));
  }

  // 获取用户是否已评论某工具
  async hasUserReviewed(userId: number, toolId: number): Promise<boolean> {
    const count = await this.reviewsRepository.count({
      where: { userId, toolId },
    });
    return count > 0;
  }

  // 更新评论状态
  async updateStatus(id: number, status: 'pending' | 'approved' | 'rejected'): Promise<Review> {
    const review = await this.findOne(id);
    review.status = status;
    return await this.reviewsRepository.save(review);
  }

  // 切换精选状态
  async toggleFeatured(id: number, isFeatured: boolean): Promise<Review> {
    const review = await this.findOne(id);
    review.isFeatured = isFeatured;
    return await this.reviewsRepository.save(review);
  }
}

